import asyncio
import time

import aiohttp
import requests
from aiohttp.web_response import Response

from config import HEADERS, SNAIL_SERVER_HOST, SNAIL_SERVER_PORT
from log import SnailLog
from schemas import (
    DispatchJobResult,
    DispatchJobResultRequest,
    JobLogTaskDTO,
    NettyResult,
    StatusEnum,
)

__all__ = ["send_heartbeat", "send_dispatch_result", "send_batch_log_report"]


async def send_heartbeat():
    """注册客户端(心跳) 协程, 在 eventloop 上运行"""
    URI = "beat"
    while True:
        try:
            reqId = time.time_ns()
            response: Response
            async with aiohttp.request(
                method="POST",
                url=f"http://{SNAIL_SERVER_HOST}:{SNAIL_SERVER_PORT}/{URI}",
                headers=HEADERS,
                json={"reqId": reqId},
            ) as response:
                data = await response.json()
                serverResponse = NettyResult(**data)
                assert reqId == serverResponse.reqId, "reqId 不一致的!"
                if serverResponse.status == StatusEnum.STATUS_SUCCESS:
                    SnailLog.LOCAL.info(f"发送心跳成功, reqId={reqId}")
                else:
                    SnailLog.LOCAL.error(f"发送心跳失败: {serverResponse.message}")
        except aiohttp.ClientError as ex:
            SnailLog.LOCAL.error(f"发送心跳失败: {ex}")

        await asyncio.sleep(30)


def send_dispatch_result(request: DispatchJobResult):
    """执行结果上报"""
    URI = "report/dispatch/result"
    reqId = time.time_ns()
    response = requests.post(
        f"http://{SNAIL_SERVER_HOST}:{SNAIL_SERVER_PORT}/{URI}",
        headers=HEADERS,
        json={
            "reqId": reqId,
            **DispatchJobResultRequest(args=[request]).model_dump(mode="json"),
        },
    )
    data = response.json()
    serverResponse = NettyResult(**data)
    assert reqId == serverResponse.reqId, "reqId 不一致的!"
    SnailLog.LOCAL.info(f"执行结果上报成功, reqId={reqId}")


def send_batch_log_report(job_log: JobLogTaskDTO):
    """日志批量上报"""
    URI = "batch/server/report/log"
    response = requests.post(
        f"http://{SNAIL_SERVER_HOST}:{SNAIL_SERVER_PORT}/{URI}",
        headers=HEADERS,
        json=job_log.model_dump(mode="json"),
    )
    data = response.json()
    serverResponse = NettyResult(**data)
    assert job_log.reqId == serverResponse.reqId, "reqId 不一致的!"
    SnailLog.LOCAL.info(f"日志批量上报成功, reqId={job_log.reqId}")
